/**
 * @file 环形石子合并
 * @author Ruiming Guo (guoruiming@stu.scu.edu.cn)
 * @brief 将 n 堆石子绕圆形操场排放，现要将石子有序地合并成一堆。
 * 规定每次只能选相邻的两堆合并成新的一堆，并将新的一堆的石子数记做该次合并的得分。
 * 请编写一个程序，读入堆数 n 及每堆的石子数，并进行如下计算：
 * 选择一种合并石子的方案，使得做 n−1 次合并得分总和最大。
 * 选择一种合并石子的方案，使得做 n−1 次合并得分总和最小。
 * @version 1.0
 * @date 2022-05-10
 *
 * @copyright Copyright (c) 2022
 *
 **/

#include <bits/stdc++.h>
using namespace std;
const int N = 210, M = N << 1, INF = 0x3f3f3f3f;

int n;
int w[M], s[M];
int f[M][M],  // 存储最大总和
    g[M][M];  // 存储最小总和

int main() {
  scanf("%d", &n);
  // 拉成两段
  for (int i = 1; i <= n; ++i) cin >> w[i], w[i + n] = w[i];

  // 预处理前缀和
  for (int i = 1; i <= n * 2; ++i) s[i] = s[i - 1] + w[i];

  memset(f, 0, sizeof(f));
  memset(g, 0x3f, sizeof(g));
  // 枚举阶段，阶段定义为合并石子段的长度
  for (int len = 1; len <= n; ++len) {  // 只枚举到 n
    for (int l = 1, r; r = l + len - 1, r < n * 2; ++l) {
      if (len == 1)
        f[l][l] = g[l][l] = 0;
      else {
        // 枚举拆分点
        for (int k = l; k + 1 <= r; ++k) {
          int merge_cost = s[r] - s[l - 1];
          f[l][r] = max(f[l][r], f[l][k] + f[k + 1][r] + merge_cost);
          g[l][r] = min(g[l][r], g[l][k] + g[k + 1][r] + merge_cost);
        }
      }
    }
  }
  int minv = 0x3f3f3f3f, maxv = -0x3f3f3f3f;
  for (int l = 1; l <= n; ++l) {
    maxv = max(maxv, f[l][l + n - 1]);
    minv = min(minv, g[l][l + n - 1]);
  }
  printf("%d\n%d\n", minv, maxv);
}
